package com.dhy.dbCore.transaction.core;

import com.dhy.dbCore.dataSource.DataSourceUtils;
import com.dhy.dbCore.transaction.util.ConnectionHolder;
import com.dhy.dbCore.transaction.util.DefaultTransactionStatus;
import com.dhy.dbCore.transaction.util.TransactionResourceManager;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * @author 大忽悠
 * @create 2022/6/6 20:37
 */
@Slf4j
public class DataSourceTransactionManager {
    private DataSource dataSource;

    public DataSourceTransactionManager(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    /**
     * 开启一个事务
     */
    public DefaultTransactionStatus getTransaction() throws SQLException {
        Connection connection = DataSourceUtils.getConnection(dataSource);
        connection.setAutoCommit(false);
        log.info("开启一个新事务");
        return new DefaultTransactionStatus(false, true, false);
    }

    public void commit(DefaultTransactionStatus status) throws Throwable {
        try {
            if (status.getIsCompleted()) {
                log.warn("事务完成后,请不要再次调用commit");
                return;
            }

            if (status.getRollBackOnly()) {
                rollback(status,null);
                return;
            }

            ConnectionHolder connectionHolder = TransactionResourceManager.getResource();
            Connection conn = null;
            if (connectionHolder != null && (conn = connectionHolder.getConnection()) != null) {
                conn.commit();
            }
            log.info("commit成功");
        } catch (SQLException e) {
            log.error("commit出错: ",e);
        }finally {
            cleanUpResource(status,false);
        }
    }

    public void rollback(DefaultTransactionStatus status,Throwable ex) throws Throwable {
        try {
            if(status==null){
                throw ex;
            }
            if (status.getIsCompleted()) {
                log.warn("事务完成后,请不要再次调用rollback");
                return;
            }
            ConnectionHolder connectionHolder = TransactionResourceManager.getResource();
            Connection conn = null;
            if (connectionHolder != null && (conn = connectionHolder.getConnection()) != null) {
                conn.rollback();
            }
            log.info("rollback成功");
            if(ex!=null){
                throw ex;
            }
        }catch (Exception e){
            log.error("rollback出错: ",e);
        }finally {
            cleanUpResource(status,false);
        }
    }

    public void cleanUpResource(DefaultTransactionStatus ts,boolean closeConn){
        TransactionResourceManager.unbindResource(closeConn);
        ts.setIsCompleted(true);
        ts.setIsNewTransaction(false);
    }
}
